package com.kexilo.config.properties;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;

/**
 * 配置插件配置属性
 * 提供完善的配置选项和IDE智能提示
 * 
 * @author Kexilo
 */
@ConfigurationProperties(prefix = "kexilo.plugin.config")
public class ConfigProperties {
    
    /**
     * 缓存策略
     */
    public enum CacheStrategy {
        NONE,       // 不缓存
        LOCAL,      // 本地缓存
        REDIS,      // Redis缓存
        HYBRID      // 混合缓存（本地+Redis）
    }
    
    /**
     * 数据源类型
     */
    public enum DataSourceType {
        DATABASE,   // 数据库
        FILE,       // 配置文件
        CONSUL,     // Consul配置中心
        NACOS,      // Nacos配置中心
        ETCD,       // ETCD配置中心
        CUSTOM      // 自定义
    }
    
    /**
     * 刷新策略
     */
    public enum RefreshStrategy {
        MANUAL,     // 手动刷新
        SCHEDULED,  // 定时刷新
        EVENT,      // 事件驱动刷新
        WATCH       // 监听文件变化刷新
    }
    
    /**
     * 是否启用配置插件
     */
    private boolean enabled = true;
    
    /**
     * 数据源类型
     */
    private DataSourceType dataSourceType = DataSourceType.DATABASE;
    
    /**
     * 缓存策略
     */
    private CacheStrategy cacheStrategy = CacheStrategy.LOCAL;
    
    /**
     * 刷新策略
     */
    private RefreshStrategy refreshStrategy = RefreshStrategy.MANUAL;
    
    /**
     * 是否启用预热
     */
    private boolean warmupEnabled = true;
    
    /**
     * 预热的配置键
     */
    private List<String> warmupKeys = new ArrayList<>();
    
    /**
     * 是否启用异步加载
     */
    private boolean asyncEnabled = true;
    
    /**
     * 是否启用配置变更监听
     */
    private boolean changeListenerEnabled = true;
    
    /**
     * 数据库配置
     */
    @Valid
    @NestedConfigurationProperty
    private DatabaseProperties database = new DatabaseProperties();
    
    /**
     * 缓存配置
     */
    @Valid
    @NestedConfigurationProperty
    private CacheProperties cache = new CacheProperties();
    
    /**
     * 文件配置
     */
    @Valid
    @NestedConfigurationProperty
    private FileProperties file = new FileProperties();
    
    /**
     * 刷新配置
     */
    @Valid
    @NestedConfigurationProperty
    private RefreshProperties refresh = new RefreshProperties();
    
    /**
     * 监控配置
     */
    @Valid
    @NestedConfigurationProperty
    private MonitorProperties monitor = new MonitorProperties();
    
    /**
     * 数据库配置属性
     */
    public static class DatabaseProperties {
        /**
         * 配置表名
         */
        @NotBlank(message = "配置表名不能为空")
        private String configTable = "sys_config";
        
        /**
         * 查询超时时间
         */
        private Duration queryTimeout = Duration.ofSeconds(30);
        
        /**
         * 是否启用批量查询
         */
        private boolean batchQueryEnabled = true;
        
        /**
         * 批量查询大小
         */
        @Min(value = 1, message = "批量查询大小必须大于0")
        private int batchSize = 100;
        
        /**
         * 是否启用事务
         */
        private boolean transactionEnabled = true;
        
        // Getters and Setters
        public String getConfigTable() { return configTable; }
        public void setConfigTable(String configTable) { this.configTable = configTable; }
        
        public Duration getQueryTimeout() { return queryTimeout; }
        public void setQueryTimeout(Duration queryTimeout) { this.queryTimeout = queryTimeout; }
        
        public boolean isBatchQueryEnabled() { return batchQueryEnabled; }
        public void setBatchQueryEnabled(boolean batchQueryEnabled) { this.batchQueryEnabled = batchQueryEnabled; }
        
        public int getBatchSize() { return batchSize; }
        public void setBatchSize(int batchSize) { this.batchSize = batchSize; }
        
        public boolean isTransactionEnabled() { return transactionEnabled; }
        public void setTransactionEnabled(boolean transactionEnabled) { this.transactionEnabled = transactionEnabled; }
    }
    
    /**
     * 缓存配置属性
     */
    public static class CacheProperties {
        /**
         * 缓存名称
         */
        private String cacheName = "kexilo-config";
        
        /**
         * 缓存键前缀
         */
        private String keyPrefix = "config:";
        
        /**
         * 缓存过期时间
         */
        private Duration expiry = Duration.ofHours(1);
        
        /**
         * 本地缓存最大条目数
         */
        @Min(value = 1, message = "本地缓存最大条目数必须大于0")
        private int localMaxSize = 500;
        
        /**
         * 缓存刷新间隔
         */
        private Duration refreshInterval = Duration.ofMinutes(10);
        
        /**
         * 是否启用缓存统计
         */
        private boolean statsEnabled = true;
        
        /**
         * 是否启用空值缓存（防止缓存穿透）
         */
        private boolean cacheNullValues = true;
        
        /**
         * 空值缓存过期时间
         */
        private Duration nullValueExpiry = Duration.ofMinutes(2);
        
        // Getters and Setters
        public String getCacheName() { return cacheName; }
        public void setCacheName(String cacheName) { this.cacheName = cacheName; }
        
        public String getKeyPrefix() { return keyPrefix; }
        public void setKeyPrefix(String keyPrefix) { this.keyPrefix = keyPrefix; }
        
        public Duration getExpiry() { return expiry; }
        public void setExpiry(Duration expiry) { this.expiry = expiry; }
        
        public int getLocalMaxSize() { return localMaxSize; }
        public void setLocalMaxSize(int localMaxSize) { this.localMaxSize = localMaxSize; }
        
        public Duration getRefreshInterval() { return refreshInterval; }
        public void setRefreshInterval(Duration refreshInterval) { this.refreshInterval = refreshInterval; }
        
        public boolean isStatsEnabled() { return statsEnabled; }
        public void setStatsEnabled(boolean statsEnabled) { this.statsEnabled = statsEnabled; }
        
        public boolean isCacheNullValues() { return cacheNullValues; }
        public void setCacheNullValues(boolean cacheNullValues) { this.cacheNullValues = cacheNullValues; }
        
        public Duration getNullValueExpiry() { return nullValueExpiry; }
        public void setNullValueExpiry(Duration nullValueExpiry) { this.nullValueExpiry = nullValueExpiry; }
    }
    
    /**
     * 文件配置属性
     */
    public static class FileProperties {
        /**
         * 配置文件路径
         */
        private String filePath = "config/application.properties";
        
        /**
         * 配置文件编码
         */
        private String encoding = "UTF-8";
        
        /**
         * 是否监听文件变化
         */
        private boolean watchEnabled = true;
        
        /**
         * 文件变化检测间隔
         */
        private Duration watchInterval = Duration.ofSeconds(5);
        
        // Getters and Setters
        public String getFilePath() { return filePath; }
        public void setFilePath(String filePath) { this.filePath = filePath; }
        
        public String getEncoding() { return encoding; }
        public void setEncoding(String encoding) { this.encoding = encoding; }
        
        public boolean isWatchEnabled() { return watchEnabled; }
        public void setWatchEnabled(boolean watchEnabled) { this.watchEnabled = watchEnabled; }
        
        public Duration getWatchInterval() { return watchInterval; }
        public void setWatchInterval(Duration watchInterval) { this.watchInterval = watchInterval; }
    }
    
    /**
     * 刷新配置属性
     */
    public static class RefreshProperties {
        /**
         * 定时刷新间隔
         */
        private Duration scheduledInterval = Duration.ofMinutes(30);
        
        /**
         * 是否启用启动时刷新
         */
        private boolean refreshOnStartup = true;
        
        /**
         * 是否启用失败重试
         */
        private boolean retryOnFailure = true;
        
        /**
         * 重试次数
         */
        @Min(value = 1, message = "重试次数必须大于0")
        private int maxRetries = 3;
        
        /**
         * 重试间隔
         */
        private Duration retryInterval = Duration.ofSeconds(5);
        
        // Getters and Setters
        public Duration getScheduledInterval() { return scheduledInterval; }
        public void setScheduledInterval(Duration scheduledInterval) { this.scheduledInterval = scheduledInterval; }
        
        public boolean isRefreshOnStartup() { return refreshOnStartup; }
        public void setRefreshOnStartup(boolean refreshOnStartup) { this.refreshOnStartup = refreshOnStartup; }
        
        public boolean isRetryOnFailure() { return retryOnFailure; }
        public void setRetryOnFailure(boolean retryOnFailure) { this.retryOnFailure = retryOnFailure; }
        
        public int getMaxRetries() { return maxRetries; }
        public void setMaxRetries(int maxRetries) { this.maxRetries = maxRetries; }
        
        public Duration getRetryInterval() { return retryInterval; }
        public void setRetryInterval(Duration retryInterval) { this.retryInterval = retryInterval; }
    }
    
    /**
     * 监控配置属性
     */
    public static class MonitorProperties {
        /**
         * 是否启用性能监控
         */
        private boolean enabled = true;
        
        /**
         * 慢查询阈值
         */
        private Duration slowQueryThreshold = Duration.ofMillis(500);
        
        /**
         * 是否启用缓存命中率监控
         */
        private boolean cacheHitRateEnabled = true;
        
        /**
         * 监控数据保留时间
         */
        private Duration dataRetentionTime = Duration.ofDays(3);
        
        /**
         * 是否启用告警
         */
        private boolean alertEnabled = false;
        
        /**
         * 缓存命中率告警阈值
         */
        @Min(value = 0, message = "告警阈值不能小于0")
        private double hitRateAlertThreshold = 0.7;
        
        // Getters and Setters
        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }
        
        public Duration getSlowQueryThreshold() { return slowQueryThreshold; }
        public void setSlowQueryThreshold(Duration slowQueryThreshold) { this.slowQueryThreshold = slowQueryThreshold; }
        
        public boolean isCacheHitRateEnabled() { return cacheHitRateEnabled; }
        public void setCacheHitRateEnabled(boolean cacheHitRateEnabled) { this.cacheHitRateEnabled = cacheHitRateEnabled; }
        
        public Duration getDataRetentionTime() { return dataRetentionTime; }
        public void setDataRetentionTime(Duration dataRetentionTime) { this.dataRetentionTime = dataRetentionTime; }
        
        public boolean isAlertEnabled() { return alertEnabled; }
        public void setAlertEnabled(boolean alertEnabled) { this.alertEnabled = alertEnabled; }
        
        public double getHitRateAlertThreshold() { return hitRateAlertThreshold; }
        public void setHitRateAlertThreshold(double hitRateAlertThreshold) { this.hitRateAlertThreshold = hitRateAlertThreshold; }
    }
    
    // Main class Getters and Setters
    public boolean isEnabled() { return enabled; }
    public void setEnabled(boolean enabled) { this.enabled = enabled; }
    
    public DataSourceType getDataSourceType() { return dataSourceType; }
    public void setDataSourceType(DataSourceType dataSourceType) { this.dataSourceType = dataSourceType; }
    
    public CacheStrategy getCacheStrategy() { return cacheStrategy; }
    public void setCacheStrategy(CacheStrategy cacheStrategy) { this.cacheStrategy = cacheStrategy; }
    
    public RefreshStrategy getRefreshStrategy() { return refreshStrategy; }
    public void setRefreshStrategy(RefreshStrategy refreshStrategy) { this.refreshStrategy = refreshStrategy; }
    
    public boolean isWarmupEnabled() { return warmupEnabled; }
    public void setWarmupEnabled(boolean warmupEnabled) { this.warmupEnabled = warmupEnabled; }
    
    public List<String> getWarmupKeys() { return warmupKeys; }
    public void setWarmupKeys(List<String> warmupKeys) { this.warmupKeys = warmupKeys; }
    
    public boolean isAsyncEnabled() { return asyncEnabled; }
    public void setAsyncEnabled(boolean asyncEnabled) { this.asyncEnabled = asyncEnabled; }
    
    public boolean isChangeListenerEnabled() { return changeListenerEnabled; }
    public void setChangeListenerEnabled(boolean changeListenerEnabled) { this.changeListenerEnabled = changeListenerEnabled; }
    
    public DatabaseProperties getDatabase() { return database; }
    public void setDatabase(DatabaseProperties database) { this.database = database; }
    
    public CacheProperties getCache() { return cache; }
    public void setCache(CacheProperties cache) { this.cache = cache; }
    
    public FileProperties getFile() { return file; }
    public void setFile(FileProperties file) { this.file = file; }
    
    public RefreshProperties getRefresh() { return refresh; }
    public void setRefresh(RefreshProperties refresh) { this.refresh = refresh; }
    
    public MonitorProperties getMonitor() { return monitor; }
    public void setMonitor(MonitorProperties monitor) { this.monitor = monitor; }
}
